package com.hr.emp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hr.classes.entity.TbWorkRecord;
import com.hr.classes.entity.dto.TbWorkRecordPerDto;
import com.hr.classes.entity.vo.TbWorkRecordPerDayVo;
import com.hr.classes.entity.vo.TbWorkRecordPerWeekVo;
import com.hr.classes.enums.WorkRecordNormalEnums;
import com.hr.classes.mapper.TbWorkRecordMapper;
import com.hr.common.retrun.R;
import com.hr.common.utils.EntityConvertUtil;
import com.hr.emp.param.EmpAdd;
import com.hr.emp.param.EmpInfo;
import com.hr.emp.service.EmpService;
import com.hr.system.entity.SysDept;
import com.hr.system.entity.SysUser;
import com.hr.system.enums.SysUserTypeEnums;
import com.hr.system.mapper.SysDeptMapper;
import com.hr.system.mapper.SysUserMapper;
import com.hr.system.util.DateUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class EmpServiceImpl implements EmpService {
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private TbWorkRecordMapper tbWorkRecordMapper;

    private static final int DAYS_OF_WEEK = 7;
    private static final int WORK_DAYS_PER_WEEK = 4;

    @Override
    public List<SysUser> getEmpList(SysUser sysUser) {
        return sysUserMapper.selectUserList(sysUser);
    }

    @Override
    public R getById(Integer id) {
        SysUser sysUser = sysUserMapper.selectById(id);
        if (Objects.isNull(sysUser)) {
            return R.error("查询失败");
        }
        return R.ok(sysUser);
    }

    @Override
    public R add(EmpAdd empAdd) {
        // 查询部门信息
        LambdaQueryWrapper<SysDept> deptWrapper = new LambdaQueryWrapper<>();
        deptWrapper.eq(SysDept::getDeptName, empAdd.getDeptName());
        SysDept sysDept = sysDeptMapper.selectOne(deptWrapper);

        SysUser sysUser = EntityConvertUtil.convert(empAdd, SysUser.class);
        if (Objects.isNull(sysUser)) {
            return R.error("内部错误");
        }
        sysUser.setType(SysUserTypeEnums.EMP.getCode());
        sysUser.setDeptId(sysDept.getId());
        System.out.println("啊实打实大苏打实打实");
        System.out.println(sysUser);
        if (sysUserMapper.insertSelective(sysUser) > 0) {
            return R.ok("新增成功");
        }
        return R.error("新增失败");
    }

    @Override
    public R batchDelete(List<Integer> idList) {
        if (sysUserMapper.deleteBatchIds(idList) > 0) {
            return R.ok("删除成功");
        }
        return R.error("删除失败");
    }

    @Override
    public R getEmpInfo(Integer id) {
        EmpInfo empInfo = sysUserMapper.getEmpInfo(id);

        if (Objects.isNull(empInfo)) {
            return R.error("查询员工详情失败");
        }

        LocalDate entryTime = empInfo.getEntryTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate now = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 计算入职时间与当前时间相差天数
        Period period = Period.between(entryTime, now);

        String workAge = period.getYears() + "年" + period.getMonths() + "月";
        empInfo.setWorkAge(workAge);

        return R.ok(empInfo);
    }

    @Override
    public R edit(EmpInfo empInfo) {
        // 修改部门
        if (StringUtils.isNotBlank(empInfo.getDeptName())) {
            LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysDept::getDeptName, empInfo.getDeptName());
            SysDept sysDept = sysDeptMapper.selectOne(wrapper);

            empInfo.setDeptId(sysDept.getId());
        }
        SysUser preUpdate = EntityConvertUtil.convert(empInfo, SysUser.class);

        int i = sysUserMapper.updateByPrimaryKeySelective(preUpdate);
        if (i > 0) {
            return R.ok("修改成功");
        }
        return R.error("修改失败");
    }

    @Override
    public R getCurWorkRecord(Integer id) {
        List<TbWorkRecordPerDayVo> result = new ArrayList<>();
        try {
            // 获取本周工作日时间段
            Date[] dates = DateUtil.calWorkDate();
            TbWorkRecordPerDto tbWorkRecordPerDto = TbWorkRecordPerDto.builder().userId(id).beginDate(dates[0]).endDate(dates[1]).build();

            // 本周打卡记录
            List<TbWorkRecord> curWeekWorkRecords = tbWorkRecordMapper.getRecordByDate(tbWorkRecordPerDto);

            for (TbWorkRecord record : curWeekWorkRecords) {
                TbWorkRecordPerDayVo vo = new TbWorkRecordPerDayVo();

                vo.setWorkDate(record.getDate());
                vo.setWorkUpRecord(record.getWorkUpRecord());
                vo.setWorkDownRecord(record.getWorkDownRecord());
                vo.setRecordResult(record.getNormal());

                if ("异常".equals(record.getNormal())) {
                    vo.setRemark(getRecordRemark(record));
                } else {
                    vo.setRemark(record.getNormal());
                }
                result.add(vo);
            }
            return R.ok(result);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return R.error("查询本周打卡记录失败");
    }

    @Override
    public R getCurMonthRecord(Integer id) {
        List<TbWorkRecordPerWeekVo> result = new ArrayList<>();
        List<List<TbWorkRecord>> data = new ArrayList<>();
        try {
            // 获取当前周开始时间 结束时间
            Date[] dates = DateUtil.calWorkDate();
            // 三周前的第一个工作日
            Date beginDate = DateUtil.calSubDate(dates[0], DAYS_OF_WEEK * 3);
            for (int i = 1; i <= 4; i++) {
                Date endDate = DateUtil.calSubDate(beginDate, -(WORK_DAYS_PER_WEEK));
                // 一周内的打卡记录
                data.add(tbWorkRecordMapper.getRecordByDate(TbWorkRecordPerDto.builder().userId(id).beginDate(beginDate).endDate(endDate).build()));

                beginDate = DateUtil.calSubDate(endDate, -3);
            }
            data.forEach(item -> result.add(dealRecordData(item)));

            return R.ok(result);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return R.error("查询近四周打卡记录失败");
    }

    /**
     * 按周统计数据
     */
    private TbWorkRecordPerWeekVo dealRecordData(List<TbWorkRecord> recordList) {
        TbWorkRecordPerWeekVo vo = new TbWorkRecordPerWeekVo();

        if (recordList.isEmpty()) {
            return vo;
        }

        String workWeek = DateUtil.getMonth(recordList.get(0).getDate()) + "月第" + DateUtil.calWhatWeek(recordList.get(0).getDate()) + "周";

        // 打卡周
        vo.setWorkWeek(workWeek);
        // 应出勤天数
        vo.setAttendDays(WORK_DAYS_PER_WEEK + 1);
        // 实际出勤天数
        vo.setAcAttendDays(recordList.size());

        int abnormalCount = (int) recordList.stream().filter(record -> WorkRecordNormalEnums.ABNORMAL.getCode().equals(record.getNormal())).count();
        // 考勤异常次数
        vo.setNumOfAbnormal(abnormalCount);
        // 异常次数占比
        vo.setPercentOfAbnormal(new DecimalFormat("0.00%").format((double) abnormalCount / vo.getAttendDays()));
        return vo;
    }

    /**
     * 获取打卡异常原因
     */
    public String getRecordRemark(TbWorkRecord tbWorkRecord) {
        Date workUpRecord = tbWorkRecord.getWorkUpRecord();
        Date workDownRecord = tbWorkRecord.getWorkDownRecord();

        // 未打卡
        if (Objects.isNull(workUpRecord) && Objects.isNull(workDownRecord)) {
            return "上下班未打卡";
        }
        if (Objects.isNull(workUpRecord)) {
            return "上班未打卡";
        }
        if (Objects.isNull(workDownRecord)) {
            return "下班未打卡";
        }
        return "考勤时间不足";
    }
}
